using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using UMC.WorkFlow.Form;

namespace UMC.WorkFlow
{
    /// <summary>
    /// 作业运行时的上下文
    /// </summary>
    public sealed class TaskRuntime
    {
        /// <summary>
        /// 作业消息
        /// </summary>
        public const string TASK_MESSAGE = "Task.Message";

        /// <summary>
        /// 作业提交的用户名
        /// </summary>
        public const string TASK_USERNAME = "Task.Username";
        /// <summary>
        /// 表示作业Id
        /// </summary>
        public const string TASK_TASK_ID = "Task.TaskId";
        /// <summary>
        /// 表示作业实例Id
        /// </summary>
        public const string TASK_INSTANCE_ID = "Task.InstanceId";
        /// <summary>
        /// 表示作业实例Id
        /// </summary>
        public const string TASK_PARENT_ID = "Task.ParentId";
        /// <summary>
        /// 表示申请时间
        /// </summary>
        public const string TASK_START_TIME = "Task.StartTime";
        /// <summary>
        /// 表示当前作业开始的状态
        /// </summary>
        public const string TASK_START_STATUS = "Task.StartStatus";
        /// <summary>
        /// 表示作业审批后的状态
        /// </summary>
        public const string TASK_END_STATUS = "Task.EndStatus";
        /// <summary>
        /// 表示当前操作的用户名
        /// </summary>
        public const string EVENT_USERNAME = "Event.Username";
        /// <summary>
        /// 表示当前事件执行时的会话ID，在一次执行时，他是唯一值
        /// </summary>
        public const string EVENT_SESSION_ID = "Event.SessionId";
        /// <summary>
        /// 表示当前操作的类型
        /// </summary>
        public const string EVENT_COMMAND_TYPE = "Event.CommandType";
        /// <summary>
        /// 表示当前操作对应的流程设计图形对应的人
        /// </summary>
        /// <remarks>
        /// （注意：event.username 与event.shape.username只有在event.username是代理时这两值才不同）
        /// </remarks>
        public const string EVENT_SHAPE_USERNAME = "Event.Shape.Username";
        /// <summary>
        /// 表示当前操作对应的流程设计图形Id
        /// </summary>
        public const string EVENT_SHAPE_ID = "Event.Shape.Id";

        private TaskEngine engne;// = new TaskEngine();
        private ulong instanceId;
        public TaskInstance Instance
        {
            get;
            private set;
        }
        private TaskRuntime(ulong instanceId)
        {
            this.instanceId = instanceId;
            this.engne = new TaskEngine(this);
            this.Instance = TaskManager.Instance(instanceId);
        }
        private TaskRuntime(TaskInstance instance)
        {
            this.engne = new TaskEngine(this);
            this.instanceId = instance.InstanceId;// ;
            this.Instance = instance;// TaskManager.Instance(instanceId);
        }
        internal TaskEngine Engine
        {
            get
            {
                return this.engne;
            }
        }
        /// <summary>
        /// 跳转
        /// </summary>
        /// <param name="shapes">图形ID集合</param>
        /// <returns></returns>
        public bool Progress(params string[] shapes)
        {
            return engne.Goto(this.Instance, shapes);
        }
        /// <summary>
        /// 注册与流程相关的数据访问事务
        /// </summary>
        /// <param name="providerKey">数据Key</param>
        /// <returns></returns>
        public static UMC.Data.Database RegisterDatabase(string providerKey)
        {
            var data = UMC.Data.Database.Instance(providerKey);
            //data.BeginTransaction();
            return data;

        }
        internal static void Submit(Identity User, ulong InstanceId, ulong TaskId, ulong ParentId, params RespondTo[] raises)
        {
            if (User == null)
            {
                throw new System.ArgumentNullException("user");
            }
            var taskNode = TaskManager.Form(TaskId);
            taskNode.InstanceId = InstanceId;
            taskNode.ParentId = ParentId;
            // var _c = _Current;
            try
            {
                var run = new TaskRuntime(taskNode);


                run.Progress(User, CommandType.Submit, raises);
            }
            finally
            {
                // _Current = _c;
            }
        }
        /// <summary>
        /// 处理作业
        /// </summary>
        /// <param name="User">用户</param>
        /// <param name="InstanceId">流程实例Id</param>
        /// <param name="TaskId">流程</param>
        /// <param name="cmdKey">操作命令</param>
        /// <param name="raises">事件回调</param>
        /// <returns></returns>
        public static TaskResult Progress(Identity User, ulong InstanceId, ulong TaskId, UMC.WorkFlow.CommandType cmdKey, params RespondTo[] raises)
        {
            if (User == null)
            {
                throw new System.ArgumentNullException("user");
            }
            TaskRuntime run = new TaskRuntime(InstanceId);
            switch (cmdKey)
            {
                case CommandType.Submit:
                    var taskNode = TaskManager.Form(TaskId);
                    if (run.Instance != null)
                    {
                        taskNode.ParentId = run.Instance.ParentId;
                    }
                    else
                    {
                        taskNode.ParentId =0;// Guid.Empty;
                    }
                    run.Instance = taskNode;
                    run.Instance.InstanceId = InstanceId;
                    goto default;
                case CommandType.Save:
                    return new TaskResult() { Success = true, InstanceId = InstanceId };
                default:
                    var result = new TaskResult();
                    if (run.Instance == null)
                    {
                        throw new System.ArgumentNullException("instance");
                    }
                    try
                    {
                        run.Progress(User, cmdKey, raises);

                        // UMC.Data.Database.Instance().Commit();
                        result.Success = true;
                        result.Message = "OK";
                        result.TaskStatus = run.Instance.Status;
                        result.Data = run.Items;
                    }
                    catch (TaskMessageException ex)
                    {

                        result.Success = false;
                        result.Message = ex.Message;
                        // UMC.Data.Database.Instance().Rollback();
                    }
                    catch (SecurityException)
                    {

                        result.Success = false;
                        result.Message = "不支持此人审批";
                        // UMC.Data.Database.Instance().Rollback();
                    }
                    catch (Exception ex)
                    {
                        // UMC.Data.Database.Instance().Rollback();
                        UMC.Data.Utility.Error("WorkFlow", ex.ToString());
                        result.Success = false;
                        result.Message = ex.Message;

                    }
                    finally
                    {
                        //maul.Set();
                        // GC.SuppressFinalize(_Current);
                        // _Current = null;
                    }
                    return result;
            }
        }
        void AppendDictionary(InstanceEvent taskEvent)
        {
            taskEvent.OnBeginProcess += new TaskEvent(taskEvent_OnBeginProcess);
            taskEvent.OnEndProcess += new TaskEvent(taskEvent_OnEndProcess);
        }

        void taskEvent_OnEndProcess(TaskInstance task, InstanceEventArgs e)
        {
            this.Items[TASK_END_STATUS] = task.Status;
            if (task.Status == TaskStatus.Completed)
            {
                if (task.ParentId != 0)
                {

                    var parent = GetInstance(task.ParentId);
                    if (parent != null)
                    {
                        // var _c = _Current;
                        var run = new TaskRuntime(parent);
                        // try
                        // {
                        run.Progress(new Identity(String.Format("~{0}", task.InstanceId.ToString()), "自动流程"), CommandType.Approval, new FormMessage(new Hashtable()).OnRespond);
                        // }
                        // finally
                        // {
                        //     // _Current = _c;
                        // }
                    }
                }
            }
        }

        void taskEvent_OnBeginProcess(TaskInstance task, InstanceEventArgs e)
        {
            this.Items[TASK_USERNAME] = task.Identity.Username;
            this.Items[TASK_TASK_ID] = task.TaskId;
            this.Items[TASK_INSTANCE_ID] = task.InstanceId;
            this.Items[TASK_START_TIME] = task.StartTime;
            this.Items[TASK_START_STATUS] = task.Status;
            this.Items[TASK_PARENT_ID] = task.ParentId;

            this.Items[EVENT_SESSION_ID] = Data.Utility.NewId();
            this.Items[EVENT_USERNAME] = e.Identity.Username;
            this.Items[EVENT_COMMAND_TYPE] = e.CommandType;
            this.Items[EVENT_SHAPE_USERNAME] = e.Shape.Identity.Username;
            this.Items[EVENT_SHAPE_ID] = e.Shape.Id;
        }
        /// <summary>
        /// 处理作业
        /// </summary>
        /// <param name="identity">身份</param>
        /// <param name="cmdKey">操作命令</param>
        /// <param name="raises">追加的处理函数</param>
        /// <returns></returns>
        void Progress(Identity identity, CommandType cmdKey, params RespondTo[] raises)
        {

            var raisesList = new List<RespondTo>(raises);
            raisesList.Insert(0, AppendDictionary);

            // TaskRuntime._Current = this;
            switch (cmdKey)
            {

                case CommandType.Submit:
                    engne.Progress(this.instanceId, identity, this.Instance, raisesList.ToArray());
                    break;
                default:
                    engne.Progress(this.Instance, identity, cmdKey, raisesList.ToArray());
                    break;
            }
            TaskManager.Instance(this.Instance);

        }

        //string Message
        //{
        //    get;
        //    set;
        //}
        IDictionary _items = new Hashtable();
        /// <summary>
        /// 获取存储在作业运行时上下文中的对象的列表
        /// </summary>
        /// <remarks>
        ///  对包含存储在作业运行时上下文中的对象的 System.Collections.IDictionary 的引用。
        /// </remarks>
        public IDictionary Items
        {
            get
            {
                return _items;
            }
        }
        // [ThreadStaticAttribute]
        // static TaskRuntime _Current;
        /// <summary>
        /// 得到正在运行的作业机制
        /// </summary>
        /// <returns></returns>
        // public static TaskRuntime Current
        // {
        //     get
        //     {
        //         return _Current;
        //     }
        // }
        /// <summary>
        /// 工作流的默认的数据库
        /// </summary>
        // public static UMC.Data.Database Database
        // {
        //     get
        //     {
        //         // var run = Current;
        //         // if (run == null)
        //         // {
        //         //     return UMC.Data.Database.Instance("TaskDbProvider");
        //         // }
        //         return RegisterDatabase("TaskDbProvider");
        //     }
        // }

        /// <summary>
        /// 验证是否是作业协同人员
        /// </summary>
        /// <param name="task">作业</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        public static bool Security(TaskInstance task, Identity identity)
        {
            if (task == null) return false;
            foreach (Shape shape in task.Shapes)
            {
                if (!String.IsNullOrEmpty(shape.Identity.Username))
                {
                    if (String.Equals(shape.Identity.Username, identity.Username, StringComparison.CurrentCultureIgnoreCase))
                    {
                        return true;
                    }
                    else if (shape.Identity.Proxy(identity, task.TaskId))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 验证是否是作业协同人员
        /// </summary>
        /// <param name="task">作业</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        public static bool Security(ulong instanceId, Identity identity)
        {
            return Security(GetInstance(instanceId), identity);
        }
        /// <summary>
        /// 获取以instanceId标示的流程事例
        /// </summary>
        /// <param name="instanceId"></param>
        /// <returns></returns>
        public static TaskInstance GetInstance(ulong instanceId)
        {
            return TaskManager.Instance(instanceId);
        }

    }
}
